﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Data.GameData
{
    public abstract class BaseObject : ICloneable
    {
        private bool isNew;
        private bool isDirty;
        private bool markedToDelete;
        private bool deleted;

        public BaseObject()
        {
            isNew = true;
            isDirty = true;
            markedToDelete = false;
            deleted = false;
        }

        #region Properties
        public bool IsNew
        {
            get { return isNew; }
            set { isNew = value; }
        }

        public bool IsDirty
        {
            get { return isDirty; }
            set { isDirty = value; }
        }

        public bool MarkedToDelete
        {
            get { return markedToDelete; }
            set { markedToDelete = value; }
        }

        public bool Deleted
        {
            get { return deleted; }
            set { deleted = value; }
        }
        #endregion

        #region Flag manipulation methods
        internal virtual void MarkNew()
        {
            IsNew = true;
            MarkedToDelete = false;
        }

        internal virtual void MarkExisting()
        {
            IsNew = false;
            IsDirty = false;
        }

        internal virtual void MarkClean()
        {
            IsDirty = false;
        }

        internal virtual void MarkDirty()
        {
            IsDirty = true;
        }

        internal virtual void MarkDeleted()
        {
            MarkedToDelete = false;
            Deleted = true;
        }

        public virtual void Delete()
        {
            MarkedToDelete = true;
            IsDirty = true;
        }
        #endregion

        public virtual void CancelChanges()
        {
            LoadValues();
            MarkExisting();
            MarkedToDelete = false;
        }

        public virtual void Save()
        {
            if (Deleted) throw new Exception("Object already deleted.");

            if (IsDirty)
            {
                Update();
                MarkExisting();
            }
        }

        public virtual void Load()
        {
            LoadValues();
            InitialiseObject();
            MarkExisting();
        }

        internal abstract void Update();

        internal abstract void DeleteNow();

        internal abstract void SaveValues();

        internal abstract void LoadValues();

        internal abstract void InitialiseObject();

        #region ICloneable Members
        /// <summary>
        /// Return a new version of this object, but assign a new objectId to it.
        /// </summary>
        /// <returns>The new version of the object</returns>
        public virtual object Clone()
        {
            BaseObject obj = this.MemberwiseClone() as BaseObject;
            obj.isNew = true;
            obj.isDirty = false;

            return obj;
        }
        #endregion
    }
}
